/**
**************************************************************************************
*Founder Effect                                                                      *
*Copyright (C) 2006-2007, 5d Studios (www.5d-Studios.com)                            *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#include "StdAfx.h"
#include "GameManager.h"
#include "Kernel.h"

extern Kernel *g_kernel;

// set the id counter
int GameManager::m_idcounter = 0;

GameManager::GameManager(void)
{
    m_current = "";
    m_prevState = "";
    m_currentState = NULL;
}

/** Initialize the game subsystem */
int GameManager::Init()
{
    return 0;
}

/** Update the current Game State */
void GameManager::Update(float  dt)
{
    // update the current state
    if ( m_currentState )
    {
        m_currentState->GetInput();
        m_currentState->Update(dt);
    }

    // The activation of the console is hard coded
    if ( g_kernel->GetInput()->IsKeyDown( SDLK_BACKQUOTE ) )
    {
        g_kernel->GetConsole()->Toggle();
        if ( g_kernel->GetConsole()->IsShowing() )
            g_kernel->GetGame()->PushState( g_kernel->GetConsole()->GetName(), true );
        else
            g_kernel->GetGame()->PopState(true); 
    }
}

/** Shutdown each state */
void GameManager::Shutdown()
{
    // save off the config -- MOVE?
    g_kernel->GetConsole()->Exec("save_cfg");

    std::string consoleName = g_kernel->GetConsole()->GetName();
    type_GameStates::iterator it;
    for(it = gameStates.begin(); it != gameStates.end(); )
    {
        if ( it->second->GetName() != consoleName ) // Shutdown each state
        {
            it->second->Shutdown();
            delete it->second;
        }
        ++it;
    }
}

/** Add a gamestate, and a game view */
void GameManager::AddState( IGameState* state, IGameStateView* stateView )
{
    state->Start();
    // create new id
    ++m_idcounter;
    // assign id
    state->SetID(m_idcounter);
    // Place the states on a stack
    gameStates[state->GetName()] = state;
    if ( stateView )
    {
        stateView->SetID(m_idcounter);
        stateView->RegisterState( state );
        // HACK - We shouldn't have to register with
        // the RenderManager here
        g_kernel->GetRenderer()->AddStateView( stateView );
    }
    // if no current state, make this current
    if ( !m_currentState )
        m_currentState = state;

    g_kernel->LPrintf( ("Added a GameState: " + state->GetName()).c_str() );
    g_kernel->LPrintf( "Reference number: %5d ", (m_idcounter-1) );
}


/** Remove a state from the stack */
void GameManager::RemoveState( IGameState* state )
{
    // shutdown this state
    state->Exit();
    state->Shutdown();

    type_GameStates::iterator it = gameStates.begin();
    for ( ; it != gameStates.end(); it++ )
    {
        if ( it->second == state )
        {
            delete it->second;
            gameStates.erase( it );
            return;
        }
            
    } 
}

/** Get the current State */
IGameState* GameManager::GetCurrentState()
{
    return m_currentState;
}


/** Activate a State */
void GameManager::SetState(const std::string stateName, bool drawOldView )
{
    if ( stateName == "" ) return;

    // save the old state
    m_prevState = m_current;
    m_current = stateName;

    IGameState* newState = gameStates[m_current];
    if ( newState ) {
        // Exit the old state
        if ( m_currentState ) {
            m_currentState->Exit();
            g_kernel->GetRenderer()->SetStateViewStatus( m_currentState->GetID(), drawOldView );
        }
        // get the current state
        m_currentState = newState;
        m_currentState->Start();
        // set the correct view
        g_kernel->GetRenderer()->SetStateViewStatus( m_currentState->GetID(), true );
    }
}

/** Push a state */
void GameManager::PushState(const std::string stateName, bool drawOldView )
{
    gameStack.push( stateName );
    SetState( stateName, drawOldView );
}

/** Load the Previous State */
void GameManager::PopState(bool keepOldActive)
{   
    if ( !gameStack.empty() )
    {   
        gameStack.pop();
        if ( !gameStack.empty() )
            SetState( gameStack.top(), keepOldActive );
    }
}

/** Deprecated */
void GameManager::GetInput()
{
    if ( m_currentState ) {
        GetCurrentState()->GetInput();
    }
}

GameManager::~GameManager(void)
{
    //g_kernel->LPrintf("Closing GameManager...");
}
